package com.hm.health.service;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import com.goodix.callback.AbsOnHBDTestClientListener;
import com.goodix.comsdk.RomaDevice;
import com.goodix.comsdk.testsdk.IHBDTestClient;
import com.goodix.iot.libbase.logger.Glog;
import com.goodix.libromablecom.sdk.cardiff.CardiffConstants;
import com.goodix.libromablecom.sdk.cardiff.arguments.GetArgumentsKeyEnum;
import com.goodix.libromablecom.sdk.cardiff.arguments.SetArgumentsKeyEnum;
import com.goodix.utils.CommonUtils;
import com.goodix.utils.SPUtils;
import com.goodix.utils.TimeUtil;
import com.hm.health.Activity.FlashReadActivity;
import com.hm.health.Activity.ecgflash.EcgFlashOnlineActivity;
import com.hm.health.MyApplication;
import com.hm.health.Utils.Constans;
import com.hm.health.Utils.TimerUtil;
import com.hm.health.entity.BleDevicesInfo;
import com.hm.health.entity.arguments.StartArgumentsManager;
import com.hm.health.records.TestRecordManager;
import com.hm.health.records.ecgpatch.EcgPatchRecord;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

public class EcgFlashService extends Service {
    public static final String TAG = "EcgFlashService";

    public static final String EXT_START_MODE = "EXT_START_MODE";
    public static final String KEY_ECG_FLASH_TESTER_INFO = "KEY_ECG_FLASH_TESTER_INFO";
    public static final String KEY_ECG_FLASH_LOST_TESTER_INFO = "KEY_ECG_FLASH_LOST_TESTER_INFO";
    public static final String KEY_ECG_FLASH_START_BUNDLE = "KEY_ECG_FLASH_START_BUNDLE";
    public static final String KEY_ECG_FLASH_START_MODE = "KEY_ECG_FLASH_START_MODE";
    public static final int NORMAL_START = 0;
    public static final int BLE_DISCONNECTED_START = 1;
    public static final int CRASH_START = 2;
    public static final int LOST_DATA_SYNC = 3;

    public static final int ERROR_FAILED = -1;

    private boolean mIsRunning;
    private EcgFlashBinder mBinder = new EcgFlashBinder();
    private List<BleDevicesInfo> mDeviceInfos = new ArrayList<>();
    private IHBDTestClient mTestClient;
    private TestRecordManager mTestRecordManager;
    private long mStartTestTime;
    private String mFunctionName;
    private TimerUtil mTimeUtil;
    private List<IEcgFlashServiceCallback> mEcgFlashCallbacks = new ArrayList<>();
    private Context mContext;
    private boolean mLostQuery = false;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate");
        mIsRunning = false;
        mLostQuery = false;
        mFunctionName = StartArgumentsManager.getInstance().getFunctionName();
        mTestClient = MyApplication.getHBDTestClient();
        Log.d(TAG, "mFunctionName=" + mFunctionName);

        // 初始化测量设备列表
        // Goodix 设备
        RomaDevice device = MyApplication.getHBDTestClient().getRomaDevice();
        BleDevicesInfo devicesInfo = new BleDevicesInfo(device.getDeviceName(),
                device.getDeviceAddress());
        mDeviceInfos.add(devicesInfo);

        mTestRecordManager = new TestRecordManager();

        mContext = this;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int mode = intent.getIntExtra(EXT_START_MODE, NORMAL_START);
        Log.d(TAG, "onStartCommand mode=" + mode);
        if (mode == CRASH_START || mode == BLE_DISCONNECTED_START) {
            if (mode == CRASH_START) {
                //启动服务时如果mcu正在采图，则恢复服务状态
                mBinder.recoveryStatus();
            }

            Bundle bundle = StartArgumentsManager.getInstance().getRecoverBundle(mContext);
            mTestClient.startHBD(bundle);
        }

        SPUtils.put(mContext, KEY_ECG_FLASH_START_MODE, LOST_DATA_SYNC);

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        mTestRecordManager.stop();
        mTestClient.unRegisterTestCallback(mOnHBDTestClientListener,null);
        stopTimer();
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public interface IEcgFlashServiceCallback {
        void onTimeUpdate(String time);
        void onStatusChanged(boolean isRunning);
        void onGetLostSectorIdFailed();
    }

    public interface ILackingPacketSaveCallback {
        void onSavedPacketNum(int savedNum);
    }

    private void startTimer() {
        Log.d(TAG, "startTimer");
        if (mTimeUtil != null && !mIsRunning) {
            mTimeUtil.startTimer();
        }
    }

    private void stopTimer() {
        if (mTimeUtil != null) {
            Log.d(TAG, "stopTimer");
            mTimeUtil.cancel();
            mTimeUtil = null;
        }
    }

    private void saveResultAndStopTest() {
        mTestRecordManager.stop();

        RawdataUploadService.uploadDirAndSubDir(mContext, Constans.ECG_FLASH_DATA_ROOT);
    }

    public class EcgFlashBinder extends Binder {
        public void startEcgFlash() {
            int sampleStatus = Integer.parseInt(
                    MyApplication.getHBDTestClient().getRunTimeFlag(GetArgumentsKeyEnum.ARG_GET_SLAVER_SAMPLE_STATUS));
            Glog.i(TAG, "sampleStatus=" + sampleStatus);
            if (sampleStatus != CardiffConstants.CARDIFF_SAMPLE_RETURN_FREE && sampleStatus != CardiffConstants.CARDIFF_RETURN_NO_RESPOND) {
                mTestClient.stopHBD();
            }
            if (!mIsRunning) {
                mStartTestTime = System.currentTimeMillis();
                mTestClient.registerTestCallback(mOnHBDTestClientListener,null);
                Bundle bundle = StartArgumentsManager.getInstance().getBundle();
                // 开始存储测试记录
                String testInfo = String.format("%s-%s", MyApplication.getInstance().getTesterInfo(), StartArgumentsManager.getInstance().getTestId());
                Log.d(TAG, "testInfo" + testInfo);
                mTestRecordManager.start(TimeUtil.formateEcgTime(mStartTestTime),
                        testInfo, mDeviceInfos, true);
//                mTestRecordManager.start(TimeUtil.formateEcgTime(mStartTestTime),
//                        SysApplication.getInstance().getTesterInfo(), mDeviceInfos, true);
                // 测试用户信息，为防止app crash进行缓存
                SPUtils.put(mContext, KEY_ECG_FLASH_TESTER_INFO, testInfo);
                SPUtils.put(mContext, KEY_ECG_FLASH_LOST_TESTER_INFO, testInfo);

                StartArgumentsManager.getInstance().cacheBundle(mContext, bundle);
                mTestClient.startHBD(bundle);
            }
        }

        public void stopEcgFlash() {
            Log.d(TAG, "mIsRunning=" + mIsRunning);
            if (mIsRunning) {
                stopTimer();
                mTestClient.stopHBD();
            }
        }

        public void finishLostSector() {
            saveResultAndStopTest();
            mFinishCallback.onSaveFinished(true);
            SPUtils.remove(mContext, KEY_ECG_FLASH_TESTER_INFO);
            mTestClient.unRegisterTestCallback(mOnHBDTestClientListener,null);
        }

        public void recoverGetLostSector() {
            mLostQuery = true;
            String testerInfo = (String)SPUtils.get(mContext, KEY_ECG_FLASH_LOST_TESTER_INFO, "unknown-unknown");
            Log.d(TAG, "testerInfo=" + testerInfo);
            // 开始存储测试记录
            mTestRecordManager.start(TimeUtil.formateEcgTime(mStartTestTime),
                    testerInfo, mDeviceInfos, true);
            Intent intent = new Intent(mContext, FlashReadActivity.class);
            mContext.startActivity(intent);
        }

        public void beginReadAllSector() {
            // 开始存储测试记录
            String testerInfo = String.format("%s-%s-%s", "default", "allSector", System.currentTimeMillis() / 1000);
            mTestRecordManager.start(TimeUtil.formateEcgTime(mStartTestTime),
                    testerInfo, mDeviceInfos, true);
        }

        public boolean isLostQuery() {
            return mLostQuery;
        }

        public boolean isEcgFlashRunning() {
            return mIsRunning;
        }

        public void forceFinish() {
            if (mTestRecordManager.getTestRecord() != null) {
                ((EcgPatchRecord)mTestRecordManager.getTestRecord()).stopQueryLostSectors();
            }
        }

        public void resetStartMode() {
            SPUtils.put(mContext, KEY_ECG_FLASH_START_MODE, NORMAL_START);
        }

        public void registerEcgFlashCallback(IEcgFlashServiceCallback callback) {
            if (!mEcgFlashCallbacks.contains(callback)) {
                mEcgFlashCallbacks.add(callback);
            }
        }

        public void unregisterEcgFlashCallback(IEcgFlashServiceCallback callback) {
            if (mEcgFlashCallbacks.contains(callback)) {
                mEcgFlashCallbacks.remove(callback);
            }
        }

        public void recoveryStatus() {
            Log.d(TAG, "recoveryStatus mIsRunning=" + mIsRunning);
            if (!mIsRunning) {
                Log.d(TAG, "recoveryStatus");
                mStartTestTime = System.currentTimeMillis();
                mTestClient.registerTestCallback(mOnHBDTestClientListener,null);

                String testerInfo = (String)SPUtils.get(mContext, KEY_ECG_FLASH_TESTER_INFO, "unknown-unknown");
                Log.d(TAG, "testerInfo=" + testerInfo);
                // 开始存储测试记录
                mTestRecordManager.start(TimeUtil.formateEcgTime(mStartTestTime),
                        testerInfo, mDeviceInfos, true);
                for (IEcgFlashServiceCallback callback : mEcgFlashCallbacks) {
                    callback.onStatusChanged(true);
                }
            }
        }

        public void startGetLostSectorId() {
            List<Integer> integerList = getLostSectorId(null);
            if (!integerList.isEmpty() && integerList.get(0) > 0) {
                Intent intent = new Intent(mContext, FlashReadActivity.class);
                mContext.startActivity(intent);
            } else {
                if (!integerList.isEmpty()) {
                    mFinishCallback.onGetLostSectorIdFailed();
                } else {
                    mBinder.finishLostSector();
                }
            }
        }

        public void forceStop() {
            if (mIsRunning) {
                mLostQuery = true;
                Executors.newSingleThreadExecutor().execute(() -> {
                    mBinder.startGetLostSectorId();
                });
            }
            mIsRunning = false;
        }

        public List<Integer> queryLostSectors(EcgPatchRecord.SyncSectorCallback callback) {
           return getLostSectorId(callback);
        }
    }

    private List<Integer> getLostSectorId(EcgPatchRecord.SyncSectorCallback callback) {
        String sectorId = MyApplication.getHBDTestClient().getRunTimeFlag(GetArgumentsKeyEnum.ALG_ECG_MAX_SECTOR_ID);
        Log.d(TAG, "BWC sector id = " + sectorId);
        String[] sectorIds = sectorId.split(",");
        List<Integer> integerList = new ArrayList<>();
        integerList.add(ERROR_FAILED);
        if (sectorIds.length > 1) {
            try {
                integerList = ((EcgPatchRecord)mTestRecordManager.getTestRecord()).startQueryLostSectors(Integer.parseInt(sectorIds[0]),
                        Integer.parseInt(sectorIds[1]), callback);
                return integerList;
            } catch (Exception e) {
                e.printStackTrace();
                return integerList;
            }
        }
        return integerList;
    }

    private AbsOnHBDTestClientListener mOnHBDTestClientListener = new AbsOnHBDTestClientListener() {
        @Override
        public void onHBDStarted(int errCode) {
            Log.d(TAG, "AbsOnHBDTestClientListener.onHBDStarted;errCode:" + errCode);
            super.onHBDStarted(errCode);
            if (EcgFlashOnlineActivity.mIsFront) {
                MyApplication.getHBDTestClient().setRunTimeFlag(SetArgumentsKeyEnum.ARG_READ_SAMPLE_DATA,
                        CardiffConstants.CARDIFF_DATA_ONLINE_ARG);
            } else {
                MyApplication.getHBDTestClient().setRunTimeFlag(SetArgumentsKeyEnum.ARG_READ_SAMPLE_DATA,
                        CardiffConstants.CARDIFF_DATA_OFFLINE_ARG);
            }
            for (IEcgFlashServiceCallback callback : mEcgFlashCallbacks) {
                callback.onStatusChanged(true);
            }
            if (!mIsRunning) {
                mTimeUtil = new TimerUtil(1000, () -> {
                    long time = System.currentTimeMillis();
                    long durationTime = Math.round((time - mStartTestTime) / 1000);
                    String timeStr = CommonUtils.SecondsToTime(durationTime);
                    if (!mEcgFlashCallbacks.isEmpty()) {
                        for (IEcgFlashServiceCallback callback : mEcgFlashCallbacks) {
                            callback.onTimeUpdate(timeStr);
                        }
                    }
                    Log.d(TAG, "cur=" + timeStr);
                });
                startTimer();
            }
            mIsRunning = true;
            mLostQuery = false;
        }

        @Override
        public void onHBDStopped(int errCode) {
            Log.d(TAG, "AbsOnHBDTestClientListener.onHBDStopped;errCode:" + errCode + ", mIsRunning" + mIsRunning);
            super.onHBDStopped(errCode);
            if (mIsRunning) {
                mLostQuery = true;
                Executors.newSingleThreadExecutor().execute(() -> {
                    mBinder.startGetLostSectorId();
                });
            }
            mIsRunning = false;
        }

        @Override
        public void onDisconnected(int errCode) {
            Log.d(TAG, "onDisconnected" + errCode);
        }
    };

    IEcgFlashFinshCallback mFinishCallback = new IEcgFlashFinshCallback() {
        @Override
        public void onSaveFinished(boolean isFinish) {
            if (isFinish) {
                Log.d(TAG, "onSaveFinished");
                for (IEcgFlashServiceCallback callback : mEcgFlashCallbacks) {
                    callback.onStatusChanged(false);
                }
            }
        }

        @Override
        public void onGetLostSectorIdFailed() {
            Log.d(TAG, "onGetLostSectorIdFailed");
            for (IEcgFlashServiceCallback callback : mEcgFlashCallbacks) {
                callback.onGetLostSectorIdFailed();
            }
        }
    };

}
